/*
 * Alan Fortes
 * 
 * Design Assignment 1
 * 
 * cpe 301, 2/24/15
 * 
 * The following program stores 25 numbers starting in the middle of the 
 * of the RAM of the ATmega328. This is found by adding the starting 
 * address of the RAM with address of the last RAM location and dividing 
 * by two. These numbers are the last eight digits of the address of the 
 * middle of the RAM. The numbers are added together and checked to see 
 * if the sum exceeds 16 bits. After this has been done, these numbers are 
 * parsed though to detect for numbers that are divisible by 7 and 3. The 
 * numbers that are divisible by 7 are all added together. All numbers 
 * divisible by 3 are added together. The sum of the numbers divisible by
 * 7 are stored in registers R20 and R21. All the numbers divisible by
 * 3 are stores in registers R23 and R24.
 */ 

.org 0
.def one = r0 //Register R0 is labled as one for reference.
.def seven = r1 //Register R0 is labled as one for reference.
.def three = r2 //Register R0 is labled as one for reference.
.def twentyFive = r3 //Register R0 is labled as one for reference.
.def dividend = r4 //Register R0 is labled as one for reference.
.def zero = r5 //Register R0 is labled as one for reference.
.def upper16 = r6 //Register R0 is labled as one for reference.
.def lower16 = r7 //Register R0 is labled as one for reference.
.def ramStartHigh = r16 //Register R0 is labled as one for reference.
.def ramStartLow = r17 //Register R0 is labled as one for reference.
.def ramEndHigh = r18 //Register R0 is labled as one for reference.
.def ramEndLow = r19 //Register R0 is labled as one for reference.
.def loader = r22 //Register R0 is labled as one for reference.

ldi loader, 0
mov zero, loader //The definitions are given their values that 
ldi loader, 1    //will be used as contants through the program.
mov one, loader
ldi loader, 3
mov three, loader
ldi loader, 7
mov seven, loader
ldi loader, 25
mov twentyFive, loader

ldi ramStartHigh, 0x01 //The upper eight bits of the address of the beginning of ram are loaded into a register. 
ldi ramStartLow, 0x00 //The lower eight bits of the address of the beginning of ram are loaded into a register. 
ldi ramEndHigh, high(ramend) //The upper eight bits of the address of the end of ram are loaded into a register. 
ldi ramEndLow, low(ramend) //The lower eight bits of the address of the end of ram are loaded into a register. 

add ramStartLow, ramEndLow //The lower eight bits of the beginning and ending of the beginning and end of ram are 
adc ramStartHigh, ramEndHigh
lsr ramStartHigh //A logic shift right is performed on the upper eight bits of the sum of the start and end of the address of the ram.
ror ramStartLow //A right order rotate is performed on the lower eight bits of the sum of the start and end of the address of the ram. This will take carry into .
mov XH, ramStartHigh //The upper and lower eight bits are placed into the X register so that we have an address to place the values.
mov XL, ramStartLow

addToMemory: 

st X, ramStartLow //The lower eight bits of the middle of the RAM are stored into the middle ram location.
dec ramStartLow //The next value to store is found by decrementing the number previously added to the memory.
dec twentyFive //The value of twentyFive decremented to keep track of how many numbers remain.
dec XL   //The address of the next value in the RAM is found by decremeting the last eight bits of the address.

cp twentyFive, one //twentyFive is compared to one. If twentyFive has fallen below one, this indicates that we have no more values to add to memory.
BRSH addToMemory  //If the previous statement is true, meaning there are still values to add to the RAM, the program jumps to the addToMemory label.
 
ldi loader, 25     //A numerical value of 25 is loaded to the loader register so that it may be moved to a non-immediate register.
mov twentyFive, loader //The register twentyFive(R3) is given a numerical value of 25 to keep tracked the values to parsed for checking for multiples of 7 and 3.
inc XL  //The lower eight bits of the address is incremented to return to the position of the top of the stack of numbers.
  
//The following loop test to see if the sum of the 25 numbers is greater than 16 bits.
//This is done so by adding the numbers one by one to the R31 and R30 registers, upper 
//and lower 8 bits respectively, and subtracting the most recent sum from 65535, which
//is the decimal equivalent of 1111111111111111, 16 bits. If the difference is less than
//the next number that is going be added to the R31 and R30 registers, the summation stops
//and the program terminates, because the result of the sum would exceed 16 bits. 
test17Bits:

ldi loader, 0xff //Hexadecimal value worth 16 bits is loaded into a pair of 
mov upper16, loader//reference registers, upper16 and lower16. 
mov lower16, loader

sub lower16, r30 //The current state of the sum, initially zero, since the first value can be added,
sbc upper16, r31 //is subtracted from 65535.

cp upper16, zero //If there is at least one active bit in the first 8 bits of the 
brne stillRoom   //difference, then it is not possible for the sum to exceed 16 bits.

cp lower16, loader //If the upper 8 bits of the sum are filled, then the possibility that the sum 
brsh stillRoom     //could exceed lies the lower 8 bits. If the amount of space remaining is equal 
jmp noRoom         //to or higher than the next number to be added, there is still room.

stillRoom:

ld loader, X //A value from the stack is loaded into a reference register.
add r30, loader //This value is then added to the R31 and R30 registers.
adc r31, zero

dec twentyFive //The count of remaining values is decremented. 
inc xl         //The address of the next number is accessed.

cp twentyFive, one //Once twentyFive has been decremented to 0, there are
BRSH test17Bits    //no more values to be assessed, and the loop terminates.

ldi loader, 25    //The value of twentyFive is reset for the parsing loop.
mov twentyFive, loader
dec XL   //The value of XL is incremented to return to the stack.

//The following loop parses through the stack of 25 numbers 
//to find out which numbers are divisible by 
parse:

ld dividend, X //A value from the stack is loaded to a register that 
               //will be continously subtracted to check for remainders.

is7: cp dividend, seven //This loop checks to see if the number is divisible by 7. This is done by first  
     BRLO doneWith7     //checking if the number is less than 7. If it is, it is ignored. If the number
					    //is 7 or greater, then it is subtracted by seven until a number less than 7 is
sub dividend, seven     //obtained.
                        
jmp is7                 
doneWith7:

cp dividend, one //This number is then compared with 1 to see if it is a remainder. Any number that is 1 or greater indicates
BRSH dontAddTo7  //a remainder and the incabaility of even division. This will cause the program to ignore the summation of this number.

ld dividend, X   //If the number has no remainder, then it is added to the R21 and R20 registers.
add r21, dividend 
adc r20, zero

dontAddTo7:

ld dividend, X //The number that was just evaluated for divisibility by 7 is reloaded to check for divisibility by 3. 
               
is3: cp dividend, three //This loop checks to see if the number is divisible by 3. This is done by first  
     BRLO doneWith3     //checking if the number is less than 3. If it is, it is ignored. If the number
	                    //is 7 or greater, then it is subtracted by seven until a number less than 3 is 
sub dividend, three     //obtained.

jmp is3
doneWith3:

cp dividend, one   //This number is then compared with 1 to see if it is a remainder. Any number that is 1 or greater indicates
BRSH dontAddTo3    //a remainder and the incabaility of even division. This will cause the program to ignore the summation of this number.

ld dividend, X     //If the number has no remainder, then it is added to the R21 and R20 registers.
add r24, dividend 
adc r23, zero

dontAddTo3:

sub twentyFive, one //The value of twentyFive is decremented to accout for the number of values remaining. 
dec XL              //The address of the next value to be assessed is found.
cp twentyFive, one  //The value of twentyFive is checked to see if we have no more values to assess. 
BRSH parse          //If the value is 0, then all 25 number have been checked.

noRoom:
inc XL    //The purpose of this instruction is to stop the program after all 
          //has been complete successfully, so that we may see the results.